package main

import (
	"bufio"
	"fmt"
	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
	"github.com/spf13/viper"
	"log"
	"os"
)

var rootCmd = &cobra.Command{
	Use:   "demo",
	Short: "A brief description of your application",
	Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
 
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	//运行命令的逻辑
	//Run: func(cmd *cobra.Command, args []string) {
	//debug
	//fmt.Println("== root命令运行成功 ==")

	//},
}

// 再定义二级子命令：
var createCmd = &cobra.Command{
	Use:   "create",
	Short: "创建书签",
}

var urlCmd = &cobra.Command{
	Use:   "url",
	Short: "Bookmark a url link ",
	Long:  "收藏一个url链接",

	//cobra 常用的参数配置校验器如下：
	//
	//MinimumNArgs(int) 当参数数目低于配置的最小参数个数时报错
	//MaximumNArgs(int) 当参数数目大于配置的最大参数个数时报错
	//ExactArgs(int)    如果参数数目不是配置的参数个数时报错
	//NoArgs            没有参数则报错

	//参数验证除了RangeArgs 还有 NoArg、ExactArgs、
	Args: cobra.RangeArgs(1, 3),

	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("link is:", link)
		if len(args) == 2 {
			fmt.Println(args[0], args[1])
		} else if len(args) == 0 {
			fmt.Println("收藏链接参数：", args)
			return
		} else {
			fmt.Println("收藏链接参数：", args)
		}
		file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
		if err != nil {
			fmt.Println(err)
		}
		//及时关闭file句柄
		defer file.Close()
		//写入文件时，使用带缓存的 *Writer
		write := bufio.NewWriter(file)
		for i := 0; i < 5; i++ {
			write.WriteString("link \n")
		}
		//Flush将缓存的文件真正写入到文件中
		write.Flush()
	},
}
var link string
var filePath string

// init 方法完成父子关系绑定，标志的初始化设置以及其他初始化工作
func init() {
	rootCmd.AddCommand(createCmd)
	createCmd.AddCommand(urlCmd)
	//持久标志，传递给所有子命令
	rootCmd.PersistentFlags().StringVarP(&filePath, "path", "p", "./bookmarks.txt", "save to txt file")
	//局部标志，仅用于具体一个子命令
	urlCmd.Flags().StringVarP(&link, "link", "l", "", "收藏链接格式： 链接地址 名称")

	//钩子函数演示
	rootCmd.AddCommand(hookCmd)
	hookCmd.AddCommand(hookSub)
	hookSub.AddCommand(hookfinal)
	////c := hookSub
	//for _, c := range rootCmd.Commands() {
	//	fmt.Println("check command:", c.Name())
	//	fmt.Println(c.Aliases)
	//	fmt.Println(c.IsAvailableCommand())
	//}
}
func main() {

	// For environment variables.
	viper.SetEnvPrefix("core")
	viper.AutomaticEnv()
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	err := doc.GenMarkdownTree(hookCmd, "/tmp")
	if err != nil {
		log.Fatal(err)
	}
}

// / 钩子函数测试
var hookCmd = &cobra.Command{
	Use:   "hookroot",
	Short: "钩子函数测试 一级",
	Long:  "测试 生命周期的不同钩子函数的继承关系",
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		fmt.Println("hookroot: PersistentPreRun")
	},
	PreRun: func(cmd *cobra.Command, args []string) {
		fmt.Println("hookroot: PreRun")
	},
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("hookroot: Running...")
	},
	PostRun: func(cmd *cobra.Command, args []string) {
		fmt.Println("hookroot: PostRun")
	},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {
		fmt.Println("hookroot: PersistentPostRun")
	},
}

// // 会继承 父命令的PersistentPreRun、PersistentPostRun
var hookSub = &cobra.Command{
	Use:   "hooksub",
	Short: "钩子函数测试 二级",
	PreRun: func(cmd *cobra.Command, args []string) {
		fmt.Println("hooksub: PreRun")
	},
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("hooksub: Running...")
	},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {
		fmt.Println("hooksub: PersistentPostRun") //覆盖了root的PersistentPostRun，并传给下级
	},
}

// // 会继承 父命令的PersistentPreRun、PersistentPostRun
var hookfinal = &cobra.Command{
	Use:     "hookfinal",
	Aliases: []string{"final", "finally"},
	Short:   "钩子函数测试 三级",
	PreRun: func(cmd *cobra.Command, args []string) {
		fmt.Println("hookfinal: PreRun")
	},
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("hookfinal: Running...")
	},
}

////output：
//go run .\helloworld.go hookroot hooksub hookfinal
//hookroot: PersistentPreRun
//hookfinal: PreRun
//hookfinal: Running...
//hooksub: PersistentPostRun/
